#include <iostream>

#include "TextureManager.h"
#include "ITexture.h"

#include <glut.h>

using namespace std;

bool lightEnabled = true;

GLfloat	lightPosX			= -6;
bool	directionForward	= true;

GLfloat	xrot;			
GLfloat	yrot;			
GLfloat	zrot;			

GLuint texId[3];
GLuint textureIndex = 0;

GLfloat	textCoordx = 0;

//Called when a key is pressed
void handleKeypress(unsigned char key, int x, int y) 
{
	switch (key) 
	{
	case 'i':
		if(lightEnabled)
			glDisable(GL_LIGHTING);
		else
			glEnable(GL_LIGHTING);
		lightEnabled = !lightEnabled;
		break;
	case 't':
		if(textureIndex >= 2)
			textureIndex = 0;
		else
			textureIndex++;
		break;
	case 27: //Escape key
		exit(0);
	}
}

//Initializes 3D rendering
void initRendering() 
{
	glClearColor(0, 0, 0, 0);
	glEnable(GL_DEPTH_TEST);
	glEnable(GL_COLOR_MATERIAL);
	glEnable(GL_LIGHTING); //Enable lighting
	glEnable(GL_LIGHT0); //Enable light #0
	glEnable(GL_LIGHT1); //Enable light #1
	glEnable(GL_LIGHT2); //Enable light #2
	glEnable(GL_NORMALIZE); //Automatically normalize normals
	glShadeModel(GL_SMOOTH); //Enable smooth shading
	glDepthFunc(GL_LESS);
	glEnable(GL_TEXTURE_2D);

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();

	gluPerspective(45, 1.0, 0.1, 100);

	/* Load PNG texture from file */
	texId[0] = *TEXTURE_MANAGER->LoadTexture(L"texture0.png")->GetId();
	texId[1] = *TEXTURE_MANAGER->LoadTexture(L"texture1.png")->GetId();
	texId[2] = *TEXTURE_MANAGER->LoadTexture(L"texture2.png")->GetId();
	if (!texId)
		exit (EXIT_FAILURE);
}

//Called when the window is resized
void handleResize(int w, int h) 
{
	glViewport(0, 0, w, h);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(45.0, (double)w / (double)h, 1.0, 200.0);
}

float _angle = -70.0f;

//Draws the 3D scene
void Render() 
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	
	glTranslatef(2, 0, -8);
	glRotatef(xrot, 1, 0, 0);
	glRotatef(yrot, 0, 1, 0);
	glRotatef(zrot, 0, 0, 1);
	glPushMatrix();
	glLoadIdentity();

	glTranslatef(-2, 0, -8);
	glRotatef(xrot, 1, 0, 0);
	glRotatef(yrot, 0, 1, 0);
	glRotatef(zrot, 0, 0, 1);
	glPushMatrix();
	glLoadIdentity();


	// LIGHT
	////Add ambient light
	GLfloat ambientColor[] = {0.2f, 0.2f, 0.2f, 1.0f}; //Color (0.2, 0.2, 0.2)
	glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientColor);
	//
	////Add positioned light
	GLfloat lightColor0[] = {0.5f, 0.5f, 0.5f, 1.0f}; //Color (0.5, 0.5, 0.5)
	GLfloat lightPos0[] = {4.0f, 0.0f, 8.0f, 1.0f}; //Positioned at (4, 0, 8)
	glLightfv(GL_LIGHT0, GL_DIFFUSE, lightColor0);
	glLightfv(GL_LIGHT0, GL_POSITION, lightPos0);
	//
	////Add directed light
	GLfloat lightColor1[] = {0.5f, 0.2f, 0.2f, 1.0f}; //Color (0.5, 0.2, 0.2)
	////Coming from the direction (-1, 0.5, 0.5)
	GLfloat lightPos1[] = {-1.0f, 0.5f, 0.5f, 0.0f};
	glLightfv(GL_LIGHT1, GL_DIFFUSE, lightColor1);
	glLightfv(GL_LIGHT1, GL_POSITION, lightPos1);

	// Triangle
	glPopMatrix();
	glEnable(GL_CULL_FACE);


	glBindTexture(GL_TEXTURE_2D, texId[0]);

	glBegin(GL_TRIANGLES);
		glTexCoord2f(textCoordx + 0.5, 0.2); glVertex3f(0.5, 1, 0);
		glTexCoord2f(textCoordx + 0.9, 0.8); glVertex3f(1, -1,  0);
		glTexCoord2f(textCoordx + 0.1, 0.8); glVertex3f(-1, -1,  0);
	glEnd();

	glBindTexture(GL_TEXTURE_2D, texId[1]);

	glBegin(GL_TRIANGLES);
		glTexCoord2f(textCoordx + 0.5, 0.2); glVertex3f(0.5, 1, 0);
		glTexCoord2f(textCoordx + 0.9, 0.8); glVertex3f(-1, -1,  0);
		glTexCoord2f(textCoordx + 0.1, 0.8); glVertex3f(1, -1,  0);
	glEnd();

	glDisable(GL_CULL_FACE);
	// Cube
	glPopMatrix();

	glBindTexture(GL_TEXTURE_2D, texId[textureIndex]);

	glBegin(GL_TRIANGLE_FAN);
						// Front
		glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);
		glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f);
		glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f,  1.0f);
		glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f,  1.0f);
	glEnd();
			
	glBegin(GL_TRIANGLE_FAN);
						// Back
		glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
		glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f);
		glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f);
		glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
	glEnd();

	glBegin(GL_TRIANGLE_FAN);
						// Top
		glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f);
		glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f,  1.0f,  1.0f);
		glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f,  1.0f,  1.0f);
		glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f);
	glEnd();

	glBegin(GL_TRIANGLE_FAN);
						// Bottom
		glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
		glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
		glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f);
		glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);
	glEnd();

	glBegin(GL_TRIANGLE_FAN);
						// Right
		glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
		glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f);
		glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f,  1.0f,  1.0f);
		glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f);
	glEnd();

	glBegin(GL_TRIANGLE_FAN);
						// Left
		glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
		glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);
		glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f,  1.0f,  1.0f);
		glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f);
	glEnd();

	xrot += 0.6;
	yrot += 0.4;
	zrot += 0.8;

	glutSwapBuffers();
}

void update(int value) {
	_angle += 1.5f;
	if (_angle > 360) {
		_angle -= 360;
	}

	if(lightPosX < -6 || lightPosX > 6)
		directionForward = !directionForward;

	if(directionForward)
		lightPosX += 0.2;
	else
		lightPosX -= 0.2;

	if(textCoordx > 1)
		textCoordx = 0;
	else
		textCoordx += 0.02;
	
	glutPostRedisplay();
	glutTimerFunc(25, update, 0);
}

int main(int argc, char** argv) {
	//Initialize GLUT
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
	glutInitWindowSize(640, 640);
	
	//Create the window
	glutCreateWindow("Lighting");
	initRendering();
	
	//Set handler functions
	glutDisplayFunc(Render);
	glutKeyboardFunc(handleKeypress);
	glutReshapeFunc(handleResize);
	
	glutTimerFunc(25, update, 0); //Add a timer
	
	glutMainLoop();
	return 0;
}








 